﻿using System;
using System.Collections.Generic;
using Microsoft.SharePoint;
using MS.InformationManagement.Core.RecordSiteQuery;
using MS.InformationManagement.Core.Support;
using MS.InformationManagement.DAL.RecordCenter;
using MS.InformationManagement.Support;
using MS.InformationManagement.Support.Constants;
using System.Linq;
using System.IO;
using System.Collections;
using DocumentFormat.OpenXml.Packaging;

namespace MS.InformationManagement.BLL.DocumentGenerator
{
    public class DocumentGeneratorBLL
    {
        public static IEnumerable<TipoDocumental> GetTemplates(int pageIndex, int pageSize, out int totalRecords)
        {
            int startingPosition = pageIndex * pageSize;
            string caml = "<OrderBy><FieldRef Name='Title' Ascending='False' /></OrderBy>";
            IEnumerable<TipoDocumental> foundElements = QueryRecordsSiteHelper<TipoDocumental>.QueryRecordsEntitiesSite(GlobalConstants.LIST_BIBLIOTECA_TIPOS_DOCUMENTALES
                , caml, new Nullable<uint>());
            totalRecords = foundElements.Count();
            return foundElements.Skip(startingPosition).Take(pageSize);
        }

        public static IEnumerable<TipoDocumental> FilterTemplates(string searchCriteria, int pageIndex, int pageSize, out int totalRecords)
        {
            if (string.IsNullOrEmpty(searchCriteria)) { return GetTemplates(pageIndex, pageSize, out totalRecords); }
            int startingPosition = pageIndex * pageSize;
            string caml = string.Format(@"<Where>
                                <Or>
                                    <Contains>
                                        <FieldRef Name='Title' />
                                        <Value Type='Text'>{0}</Value>
                                     </Contains>
                                     <Contains>
                                        <FieldRef Name='FileLeafRef' />
                                        <Value Type='Text'>{0}</Value>
                                     </Contains>
                                  </Or>
                               </Where>
                               <OrderBy>
                                  <FieldRef Name='Title' Ascending='False' />
                                </OrderBy>", searchCriteria);
            IEnumerable<TipoDocumental> foundElements = QueryRecordsSiteHelper<TipoDocumental>.QueryRecordsEntitiesSite(GlobalConstants.LIST_BIBLIOTECA_TIPOS_DOCUMENTALES
                , caml, new Nullable<uint>());
            totalRecords = foundElements.Count();
            return foundElements.Skip(startingPosition).Take(pageSize);
        }

        public static string SaveDocument(string docName, Guid libraryID, string templatePath)
        {
            string newDocPath = string.Empty;
            byte[] template = null;
            string fileExtension = string.Empty;
            string fileName = string.Empty;

            string recordsSiteUrl = ConfigurationHelper.GetInstance().ConfigItems[GlobalConstants.SITE_RECORDS_URL];
            string templateFileExtension = templatePath.Substring(templatePath.LastIndexOf('.') + 1);
            string libraryName = SPContext.Current.Web.CurrentUser.LoginName;
            libraryName = libraryName.Substring(libraryName.LastIndexOf('\\') + 1);

            fileExtension = GetFileExtension(templatePath);

            fileName = string.Format("{0}.{1}", docName.TrimStart(), fileExtension);

            using (SPSite recordsSite = new SPSite(recordsSiteUrl))
            {
                using (SPWeb recordsSiteWeb = recordsSite.OpenWeb())
                {
                    template = recordsSiteWeb.GetFile(templatePath).OpenBinary();
                }
            }


            SPContext.Current.Web.AllowUnsafeUpdates = true;
            SPFile newFile = SPContext.Current.Web.Lists[libraryID].RootFolder.Files.Add(fileName, template, false);
            newFile.Item[SPBuiltInFieldId.ContentType] = GlobalConstants.CTTN_ARCHIVE;
            newFile.Item[CustomSiteColumns.FIELD_DOCSET_KIND] = TermStoreHelper.GetTaxonomyFieldByTerm(GlobalConstants.METADATA_GROUP_NAME, GlobalConstants.METADATA_TERM_TIPOS, GlobalConstants.METADATA_TERM_TIPO_SIN_RADICADO);
            newFile.Item[CustomSiteColumns.FIELD_DOCUMENT_STATUS] = TermStoreHelper.GetTaxonomyFieldByTerm(GlobalConstants.METADATA_GROUP_NAME, GlobalConstants.METADATA_TERM_STATUS, GlobalConstants.METADATA_TERM_STATUS_SIN_RADICADO);
            newFile.Item[CustomSiteColumns.FIELD_DOCSET_ID_RADICADO] = fileName;
            newFile.Log(string.Empty, DateTime.Now, InformationManagement.Support.Enums.TraceableOperation.Creación, SPContext.Current.Web.CurrentUser.Name, string.Empty);
            newFile.Item.SystemUpdate();
            SPContext.Current.Web.AllowUnsafeUpdates = false;
            newDocPath = string.Format("{0}/{1}", SPContext.Current.Web.Url, newFile.Url);

            return newDocPath;
        }

        public static bool FileExists(string fileName, Guid libraryID, string templatePath)
        {
            bool exists = false;
            if (fileName.TrimEnd().TrimStart().Equals(string.Empty)) return true;
            SPDocumentLibrary SPTargetLibrary = SPContext.Current.Web.Lists.GetList(libraryID, false) as SPDocumentLibrary;
            string filePath = string.Format("{0}/{1}/{2}.{3}", SPContext.Current.Web.Url, SPTargetLibrary.Title, fileName.TrimEnd().TrimStart(), GetFileExtension(templatePath));
            SPFile foundFile = SPContext.Current.Web.GetFile(filePath);
            exists = foundFile.Exists;
            return exists;
        }

        private static string GetFileExtension(string templatePath)
        {
            string fileExtension = string.Empty;
            string templateFileExtension = templatePath.Substring(templatePath.LastIndexOf('.') + 1);

            switch (templateFileExtension)
            {
                case GlobalConstants.WORD:
                    fileExtension = "docx";
                    break;
                case GlobalConstants.WORD_LEGACY:
                    fileExtension = "doc";
                    break;
                case GlobalConstants.EXCEL:
                    fileExtension = "xlsx";
                    break;
                case GlobalConstants.EXCEL_LEGACY:
                    fileExtension = "xls";
                    break;
                case GlobalConstants.POWERPOINT:
                    fileExtension = "pptx";
                    break;
                case GlobalConstants.POWERPOINT_LEGACY:
                    fileExtension = "ppt";
                    break;
            }

            return fileExtension;
        }

        public static void SaveDocumentType(string fileName, string title, string code, double? version, DateTime? creationDate, Stream fileStream)
        {
            string fileExtension = GetFileExtension(fileName);
            byte[] data = new byte[(Int32)fileStream.Length];
            fileStream.Read(data, 0, (Int32)fileStream.Length);
            using (MemoryStream officeFileStream = new MemoryStream())
            {
                officeFileStream.Write(data, 0, data.Length);
                OfficeWordHelper.RemoveCoreProperties(officeFileStream, fileExtension);
                
                SPDocumentLibrary targetLibrary = SPContext.Current.Web.GetList(
                string.Format("{0}/{1}", SPContext.Current.Web.Url, GlobalConstants.LIST_BIBLIOTECA_TIPOS_DOCUMENTALES)) as SPDocumentLibrary;
                if (targetLibrary == null) { throw new Exception("La biblioteca de tipos de documentos no existe"); }

                Hashtable properties = new Hashtable();
                properties.Add("vti_title", title);
                properties.Add(CustomSiteColumns.FIELD_VERSION, version.HasValue ? Convert.ToInt32(version.Value) : new Nullable<int>());
                properties.Add(CustomSiteColumns.FIELD_CODE, code);
                properties.Add(CustomSiteColumns.FIELD_TEMPLATE_CREATION_DATE, creationDate);

                SPContext.Current.Web.AllowUnsafeUpdates = true;
                SPFile item = targetLibrary.RootFolder.Files.Add(fileName, officeFileStream, properties, false);
                SPContext.Current.Web.AllowUnsafeUpdates = false;
            }

        }

        public static void UpdateDocumentType(int id, string fileName, string title, string code, double? version, DateTime? creationDate, Stream fileStream)
        {
            SPDocumentLibrary targetLibrary = SPContext.Current.Web.GetList(
                string.Format("{0}/{1}", SPContext.Current.Web.Url, GlobalConstants.LIST_BIBLIOTECA_TIPOS_DOCUMENTALES)) as SPDocumentLibrary;
            if (targetLibrary == null) { throw new Exception("La biblioteca de tipos de documentos no existe"); }

            SPListItem targetItem = targetLibrary.GetItemById(id);
            if (targetItem == null) { throw new Exception(string.Format("No existe una plantilla de documento con el id {0} en la biblioteca de tipos documentales", id)); }

            if (!string.IsNullOrEmpty(fileName))
            {
                string oldExtension = targetItem[CustomSiteColumns.FIELD_SP_DOC_ICON].ToString();
                string extension = fileName.Substring(fileName.LastIndexOf('.') + 1);
                if (!extension.ToUpper().Equals(oldExtension.ToUpper())) { throw new Exception(string.Format("Esta intentando actualizar la plantilla con un archivo cuyo tipo ({0}) no coincide con el archivo original ({1})", extension, oldExtension)); }
            }

            SPContext.Current.Web.AllowUnsafeUpdates = true;

            targetItem[SPBuiltInFieldId.Title] = title;
            targetItem[CustomSiteColumns.FIELD_TEMPLATE_CREATION_DATE] = creationDate;
            targetItem[CustomSiteColumns.FIELD_CODE] = code;
            targetItem[CustomSiteColumns.FIELD_VERSION] = version;

            if (!string.IsNullOrEmpty(fileName))
            {
                targetItem[CustomSiteColumns.FIELD_DOCSET_NAME] = fileName;
            }

            targetItem.Update();

            if (fileStream != null)
            {
                targetItem.File.CheckOut();
                targetItem.File.SaveBinary(fileStream);
                targetItem.File.CheckIn(string.Empty);
                targetItem = targetLibrary.GetItemById(id);
                targetItem[SPBuiltInFieldId.Title] = title;
                targetItem.Update();
            }

            SPContext.Current.Web.AllowUnsafeUpdates = false;
        }

        public static TipoDocumental GetDocumentType(int id)
        {
            TipoDocumental targetDocumentType = new TipoDocumental();
            SPDocumentLibrary targetLibrary = SPContext.Current.Web.GetList(
                string.Format("{0}/{1}", SPContext.Current.Web.Url, GlobalConstants.LIST_BIBLIOTECA_TIPOS_DOCUMENTALES)) as SPDocumentLibrary;
            if (targetLibrary == null) { throw new Exception("La biblioteca de tipos de documentos no existe"); }

            SPListItem targetItem = targetLibrary.GetItemById(id);
            if (targetItem == null) { throw new Exception(string.Format("No existe una plantilla de documento con el id {0} en la biblioteca de tipos documentales", id)); }

            targetDocumentType.Código = targetItem[CustomSiteColumns.FIELD_CODE] == null ? string.Empty : targetItem[CustomSiteColumns.FIELD_CODE].ToString();
            targetDocumentType.FechaDeCreación = targetItem[CustomSiteColumns.FIELD_TEMPLATE_CREATION_DATE] == null ? new Nullable<DateTime>() :
                Convert.ToDateTime(targetItem[CustomSiteColumns.FIELD_TEMPLATE_CREATION_DATE]);
            targetDocumentType.Id = targetItem.ID;
            targetDocumentType.Name = targetItem.File.Name;
            targetDocumentType.Versión = targetItem[CustomSiteColumns.FIELD_VERSION] == null ? new Nullable<Double>() :
                Convert.ToDouble(targetItem[CustomSiteColumns.FIELD_VERSION]);
            targetDocumentType.Title = targetItem.Title;

            return targetDocumentType;
        }
    }
}
